/*
* plist parser v0.3
* by Nicolas Alvarez
*
* You're free to do anything with this code, as long as you give me credit.
* (I keep looking for a one-line real license; most are longer than the code
* below)
*
* New in this version: date support!
*
* Elements supported:
* - <dict>
* - <array>
* - <string>
* - numbers (<integer> and <real>)
* - booleans (<true/> and <false/>)
* - <date> (probably not supporting the full ISO8601 format, but should be
* close; timezones are supported)
*
* <data> (base64 binary data) is not supported; returns null.
*/

function parse_plist(xml)
	{
	function parse_internal(elem)
		{
		switch (elem.tagName) {
		case 'dict':
			var ret = {};
			var child, key = null;
			for (child = elem.firstChild; child != null; child = child.nextSibling) {
				if (child.nodeType != DOMNode.ELEMENT_NODE) {
					continue;
				}
				if (child.tagName == 'key') {
					key = child.firstChild.nodeValue;
				} else {
					ret[key] = parse_internal(child);
				}
			}
			return ret;
		case 'array':
			var ret = [];
			var child;
			for (child = elem.firstChild; child != null; child = child.nextSibling) {
				if (child.nodeType != DOMNode.ELEMENT_NODE) {
					continue;
				}
				ret.push(parse_internal(child));
			}
			return ret;
		case 'string':
			return elem.firstChild.nodeValue;
		case 'integer':
			return parseInt(elem.firstChild.nodeValue);
		case 'real':
			return parseFloat(elem.firstChild.nodeValue);
		case 'true':
			return true;
		case 'false':
			return false;
		case 'data':
			return null; //not implemented
		case 'date':
			var str = elem.firstChild.nodeValue;
			var m = str.match(/^(\d{4})-?(\d\d)-?(\d\d)T(\d\d):?(\d\d):?(\d\d)(?:(Z)|([+-]\d\d)(?::?(\d\d))?)$/);
			
			for(var i=1; i<=6; i++) {
				m[i] = parseInt(m[i], 10);
			}
			
			var tz_offset = 0;
			if (m[7] != 'Z') {
				tz_offset = parseInt(m[8])*60 + parseInt(m[9]);
			}
			
			var d = new Date();
			//I have to use the methods, because the constructor takes local
			//time values, not UTC
			d.setUTCFullYear(m[1]);
			d.setUTCMonth(m[2]);
			d.setUTCDate(m[3]);
			d.setUTCHours(m[4]);
			d.setUTCMinutes(m[5] + tz_offset);
			d.setUTCSeconds(m[6]);
			d.setUTCMilliseconds(0);
			
			return d;
		default:
			throw new Error("unknown tag: "+elem.tagName);
		}
	}
	var dom = XMLDOM.parse(xml);
	return parse_internal(dom.getElementsByTagName('plist').item(0).firstChild);
}
